package game;

import game.evolver.DeckEvolverMain;

import java.util.ArrayList;

public class Game {
	
	int opponentLife;
	Deck deck;
	ArrayList<Card> hand;
	ArrayList<Card> board;
	ArrayList<Card> opponentBoard;
	ArrayList<Card> graveyard;
	int turn;
	boolean win;
	double bestScore = 999999d;
	String bestDeck = "NOT FOUND";

	boolean displayActions = false;
    boolean useEasyOpponent = false;
	boolean landPlayedThisTurn;
    
    public static final int PENTALY_FOR_NOT_WINNING = 30; // if we run out of cards or take over X turns
    
	public static void main(String args[]) {
		Game g = new Game();
//		for (int numMountains = 15; numMountains<=60; numMountains++) {
//			int max = 60 - numMountains;
//	    	for (int numGoblins = 0; numGoblins<=max; numGoblins++) {
//	    		max = max - numGoblins;
//	    		for (int numLightningBolts = 0, numBallLightnings = max; numLightningBolts<=max && numBallLightnings>=0; numLightningBolts++, numBallLightnings--) {
//	    			g.playGameSeries(numMountains, numGoblins, numLightningBolts, numBallLightnings);
//	    		}
//	    	}
//	    }
		
		g.displayActions = true;
		
		int[] quantities = {10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7};
		
		Deck newDeck = new Deck(DeckEvolverMain.cardNames, quantities);
		g.playGame(newDeck);
		
	}

	public  double playGameSeries(CardName[] names, int[] cardQuantities) {
		int count = 0;
		int numberOfGames = 2000; // 10k seems the best mix of accuracy and performance
		
		
		for (int i=0; i < numberOfGames; i++) {
			Deck newDeck = new Deck(names, cardQuantities);
			count += playGame(newDeck);
		}
		double average = (double)count/(double)numberOfGames;
		return average;
	}
	
	public int playGame(Deck newDeck) {
		setEverythingToDefaultStaartingValues(newDeck);
		for (int i = 0; i < 6; i++) { // we start with 6 cards, not 7 since we always draw one at start of hand.
			// draw a card
			try {
				drawCard();
			} catch (IndexOutOfBoundsException e) {
				// we have run out of cards, end the game
				return PENTALY_FOR_NOT_WINNING;				
			}

		}
		
		if (Math.random()>0.5) {
			displayAction("Opponent wins toss and starts game.");
			// draw a card
			try {
				drawCard();
			} catch (IndexOutOfBoundsException e) {
				// we have run out of cards, end the game
				return PENTALY_FOR_NOT_WINNING;				
			}
			doOpponentTurn();
		} else {
			displayAction("Player wins toss and starts game.");			
		}
		
		while (opponentLife > 0 && turn < 15) {
			landPlayedThisTurn = false;
			displayAction("Player turn : " + turn);
			removeSummoningSickness();
			untapAll();
			
			// draw a card
			try {
				drawCard();
			} catch (IndexOutOfBoundsException e) {
				// we have run out of cards, end the game
				displayAction("LOSS. No more cards in deck!");
				return PENTALY_FOR_NOT_WINNING;				
			}
			
//			lay a land
			playNonTeeteringPeaksLand();

//			if opponent can be killed with dd and creature sacrifice, do that
			if (canKillOpponentWithDD()) {
				doGameWin();
				return turn;
			}			
			
//			use any dd on creatures (lowest damage first) if *I* have any creatures, otherwise don't bother (and bolt opponent later)
			if (boardHasCreaturesThatCanAttack(board)) {
				useDDOnCreatures();
			}
			
			handleUnearthCards();
			
//			play creatures
			playCreaturesFromHand();
			
			if (!landPlayedThisTurn) {
				playTeeteringPeaks();
			}		
			
//			attack
			doAttack();

			if (opponentLife <= 0) {
				doGameWin();
				return turn;
			}
			
//			recheck dd and creature sacrifice.
			if (canKillOpponentWithDD()) {
				doGameWin();
				return turn;
			}
			
			//if mana is available
			// cast a DD spell
			// until no mana is available/no DD spells left/not enough mana is available for DD spells left in hand
			
			// always try to cast the highest cost card first
			ArrayList<Card> tempHand = new ArrayList<Card>();
			
			Card card = getHighestCostCard(hand, getAvailableMana(board), "INSTANT", "Searing Blaze");
			while (card!= null) { // Searing Blaze is creature-only. TODO: handle this better for edge cases. Note that if can kill opponent with DD then it's OK to use on own creatures if needed.
				if (card.isHasKicker() && getAvailableMana(board) >=card.getCostWithKicker()) { // kicker is always more expensive, right?
					castSpellWithKicker(card);
				} else if (!card.isHasKicker() && getAvailableMana(board) >=card.getCost()) {
					castSpell(card); // this is OK since we have already established we can't kill with DD this turn (TODO: but still not optimal - should look ahead)
				} else {
					tempHand.add(card);
					hand.remove(card);
				}
				card = getHighestCostCard(hand, getAvailableMana(board), "INSTANT", "Searing Blaze");
			}
			for (Card c : tempHand) {
				hand.add(c); // add the temporarily-excluded cards back into the hand
			}
			
			// TODO: handle the targetting of opposing creatures so that the best creature is targetted each time
						
			// at end of turn, destroy all creatures that only last until end of turn
			ArrayList<Card> tempBoard = new ArrayList<Card>();
			for (Card c : board) {
				tempBoard.add(c);
			}
			for (Card c : tempBoard) {
				if (c.isRemoveAtEndOfTurn()) {
					board.remove(c);					
					if (!c.isHasBeenUnearthedAlready()) {
						c.untap();						
						displayAction("Removing " + c.getName() + " from play at end of turn.");
						putInGraveyard(c);
					} else {
						displayAction("Removing " + c.getName() + " from play at end of turn. (Permanently removed)"); // otherwise it's removed entirely
					}
				}
			}
			
			
			// if cards > 7, discard highest cost card, or land if total land >=4
			// TODO: doHandCleanup();
			
			displayAction("End of Turn: " + turn + " Opponent life: " + opponentLife + " Graveyard size: " + graveyard.size() + " Hand Size: " + hand.size());
			if (win) {
				return turn;
			}
			turn++;
			doOpponentTurn();
		}
		// if turn ==10, doGameLoss()
		return PENTALY_FOR_NOT_WINNING; // penalty for not winning in 10 turns
	}

	private void drawCard() {
		Card c = deck.draw();
		displayAction("Draw card: " + c.getName());
		hand.add(c);
	}

	// TODO: This is limited to instants for now, handle the rest!
	private void castSpellWithKicker(Card c) {
		tapLands(c.getCostWithKicker());
		hand.remove(c);
		displayAction("Casting " + c.getName() + " with KICKER.");
		if (c.getType().equals("INSTANT")) {
			// for now, assume it's a bolt
			opponentLife -= c.getDamageWithKicker();			
		} else {
			System.out.println("Attempt to cast a non-instant card with kicker! This is not fully supported!");
			if (c.getType().equals(CardFactory.CREATURE) || !c.isHasHaste()) {
				c.setSummoningSick(true);
				displayAction(c.getName() + " gains summoning sickness.");
			}
			board.add(c);
		}
		
	}

	// Finds the most expensive card in the source that costs availableMana or less
	private Card getHighestCostCard(ArrayList<Card> source, int availableMana, String type, String cardToExclude) {
		int cost = Integer.MIN_VALUE;
		Card card = null;
		for (Card c : source) {
			if (c.getType().equals(type) && !c.getName().equals(cardToExclude) && (c.getCost() > cost || c.getCostWithKicker() > cost)) {
				card = c;
			}
		}
		return card; // remember to handle null
	}

	private void removeSummoningSickness() {
		for (Card c : board) {
			if (c.isSummoningSick()) {
				c.setSummoningSick(false);
				displayAction("Removing summoning sickness from " + c.getName());
			}
		}		
	}

	private void setEverythingToDefaultStaartingValues(Deck newDeck) {
		win = false;
		displayAction("Starting game");
		opponentLife = 20;
		turn = 1;
		deck = newDeck;
		hand = new ArrayList<Card>();
		board = new ArrayList<Card>();
		graveyard = new ArrayList<Card>();
		opponentBoard = new ArrayList<Card>();
		landPlayedThisTurn = false;
	}

	private void playTeeteringPeaks() {
		// play Teetering Peaks last (TODO: do this more intelligently. in particular, cast a haste creature THEN play a land)
		ArrayList<Card> tempHand = new ArrayList<Card>();
		for (Card c : hand) {
			tempHand.add(c);
		}
		for (Card c : tempHand) {			
			if (c.getName().equals("Teetering Peaks")) {
				hand.remove(c);
				board.add(c);
				c.tap(); // comes into play tapped
				landPlayedThisTurn = true;
				displayAction("Playing card: " + c.getName());
				// TODO: trigger landfall
				
				// TODO: make this go onto the stack e.g. stack.addEffect(blah)
				Card cardToPump = null;
				for (Card tempCard : board) {
					if (tempCard.isTapped() || !tempCard.getType().equals(CardFactory.CREATURE)) {
						continue;
					}
					if (tempCard.isFlying()) {
						if (cardToPump != null) {
							// put it on the card with the LOWEST power (TODO: MAke this better - e.g. if trample AND flying then it's a better target etc.
							if (cardToPump.getPower() > tempCard.getPower()) {
								cardToPump = tempCard;
							} // otherwise do nothing
							
						} else {
							cardToPump = tempCard;
						}
					} else if (tempCard.isTrample()) {
						if (cardToPump != null) {
							 if (cardToPump.isFlying()) {
								 continue;
							 } else {
								 // put it on the card with the LOWEST power (TODO: MAke this better - e.g. if trample AND flying then it's a better target etc.
								 if (cardToPump.getPower() > tempCard.getPower()) {
									 cardToPump = tempCard;
								 } // otherwise do nothing								 
							 }
						} else {
							cardToPump = tempCard;
						}						
					} else {
						// regular ground creature
						if (cardToPump != null) {
							if (cardToPump.isFlying() || cardToPump.isTrample()) {
								continue;
							} else {
								// put it on the card with the LOWEST power (TODO: MAke this better - e.g. if trample AND flying then it's a better target etc.
								 if (cardToPump.getPower() > tempCard.getPower()) {
									 cardToPump = tempCard;
								 } // otherwise do nothing
							}
						} else {
							cardToPump = tempCard;
						}
					}					
				}
				
				if (cardToPump == null) {
					// TODO: Technically, we need to target an opponents creature if one exists
					// for now, do nothing
				} else {
					displayAction("Pumping (+2/+0) " + cardToPump.getName());
					cardToPump.addPowerUntilEndOfTurn(2);
				}
				
				return;
			}
		}

		
	}

	private void putInGraveyard(Card c) {
		c.clearAllModifiers(); // removes all tokens, temporary bonuses etc.
		graveyard.add(c);
		displayAction(c.getName() + " goes to graveyard");		
	}

	private void handleUnearthCards() {
		ArrayList<Card> tempGraveyard = new ArrayList<Card>();
		for (Card c : graveyard) {
			tempGraveyard.add(c);
		}
		for (Card c : tempGraveyard) {
			// TODO: add in preference for maximizing mana use to get most
			// possible creatures out.
			if (c.getType().equals("CREATURE")) {
				if (getAvailableMana(board) >= c.getUnearthCost()) { // most cards have an unearth cost of max integer (not unearthable)
					tapLands(c.getUnearthCost());
					graveyard.remove(c);
					c.setHasBeenUnearthedAlready(true);
					displayAction("Unearth: Casting " + c.getName());
					if (c.getType().equals(CardFactory.INSTANT)) {
						// for now, assume it's a bolt-like spell if instant
						opponentLife -= c.getDamage();			
					} else {
						board.add(c);
					}
				}
			}
		}
		
	}

	private boolean boardHasCreaturesThatCanAttack(ArrayList<Card> board2) {
		boolean foundOne = false;
		for (Card c : board) {
			if (c.getType().equals("CREATURE") && !c.isTapped() && !c.isSummoningSick()) {
				if (c.isCanOnlyAttackWithOtherCreatures() && foundOne==false) {
					foundOne=true;
					continue;
				} else {
					return true;
				}
			}
		}
		return false;
	}

	private void doAttack() {

		// TODO: check if you can bolt after entering the combat phase but before assigning attackers, or if that puts you back in main phase
		
		// TODO: have opponent bolt creatures here sometimes
		
		// TODO: remove the assumption that all creatures have haste
		ArrayList<Card> attacking = new ArrayList<Card>();
		ArrayList<Card> attackingWithFlying = new ArrayList<Card>();
		ArrayList<Card> blocking = new ArrayList<Card>();
		
		
		
		ArrayList<Card> tempBoard = new ArrayList<Card>();
		for (Card c : board) {
			tempBoard.add(c);
		}
		for (Card c : tempBoard) {
			if (c.getType().equals("CREATURE") && !c.isTapped() && !c.isSummoningSick()) {
				c.tap();
				if(c.isFlying()) {
					attackingWithFlying.add(c);
				} else {
					attacking.add(c);
				}
				board.remove(c);
				displayAction("Attacking with: " + c.getName() + "  Has flying: " + c.isFlying());
			}
		}
		
		int totalAttackingCreatues = (attacking.size() + attackingWithFlying.size()); 
		displayAction("Total attacking creatures: " + totalAttackingCreatues);
		if (totalAttackingCreatues == 1) {
			Card c = null;			
			if (attacking.size() > 0) {
				c = attacking.get(0);
			} else {
				c = attackingWithFlying.get(0);
			}
			if (c.isCanOnlyAttackWithOtherCreatures()) {
				displayAction("Tried to attack with " + c.getName() + " but this can only attack with other creatures, so ending attack.");
								
				for (Card card : attacking) {
					board.add(card);
				}
				for (Card card : attackingWithFlying) {
					board.add(card);
				}
				return; // don't continue since we have 0 creatures to attack with
			}
		}
		
		// TODO: tap the atackers
		
		
		ArrayList<Card> tempOpponentBoard = new ArrayList<Card>();
		for (Card c : opponentBoard) {
			tempOpponentBoard.add(c);
		}
		for (Card c : tempOpponentBoard) {
			if (c.getType().equals("CREATURE") && !c.isTapped()) {
				blocking.add(c);
				opponentBoard.remove(c);
				displayAction("Potntially blocking with: " + c.getName());
			}
		}
		
		// TODO: sort attackers largest to smallest, and defenders smallest to largest
		
		
		// TODO: Handle gang-blocking non-trample creatures in order to kill a bigger creature (if appropriate)
		
		ArrayList<Card> attackersToRemove = new ArrayList<Card>();
		ArrayList<Card> blockersToRemove = new ArrayList<Card>();
		
		int trampleDamage = 0;
		int extraBlockers = 0;
		int trampleDamageReduction = 0;
		// compare pow and tou to see who dies and how much damage (if any) is overflow
		if (blocking.size() > attacking.size()) {
			extraBlockers = blocking.size()-attacking.size();
		}
		for (int i = 0; i < attacking.size() && i < blocking.size(); i++) {
			Card attacker = attacking.get(i);
			Card blocker = blocking.get(i);
			int bonusDamageToAttacker = 0;
			// TODO: handle first strike, trample etc
			
			if (attacker.getPower() >= blocker.getToughness()) {
				// remove blocker at end of combat
				blockersToRemove.add(blocker);
				// Handle spillover trample damage
				if (attacker.isTrample()) {
					
					trampleDamage += attacker.getPower() - blocker.getToughness();
					// add more blocking creatures here if there are any by grabbing the next creature that can block but is not
					// (get the one with the most damage) and keep adding until all of the damage is blocked or we run out of creatures
					while (extraBlockers >0) {
						Card extraBlocker = blocking.get(attacking.size() -1 + extraBlockers);
						displayAction(extraBlocker.getName() + " also blocks " + attacker.getName());
						trampleDamageReduction += extraBlocker.getToughness();
						trampleDamage -= trampleDamageReduction;
						trampleDamage = Math.max(trampleDamage, 0); // minimum damage is 0. can't have negative damage
						bonusDamageToAttacker += extraBlocker.getPower();						
						if (trampleDamage > 0) {
							blockersToRemove.add(extraBlocker);
						}
						extraBlockers--;
					}
					
				}
			}
			if (blocker.getPower() + bonusDamageToAttacker >= attacker.getToughness()) {
				// remove attacker at end of combat
				attackersToRemove.add(attacker);
			}			
		}	
		
		// TODO: handle multiple blockers ganging up on a single person 
		    // plus handle the player then bolting before damage
		    // plus handle the opponent not doing this if they will let through enough damage to die
		
		opponentLife -= trampleDamage;
		displayAction("Opponent loses " + trampleDamage + " life from trample damage.");
		
		int flyingDamage = 0;
		for (Card c : attackingWithFlying) { // TODO: handle blocking fliers
			flyingDamage += c.getPower();
		}
		opponentLife -= flyingDamage;
		displayAction("Opponent loses " + flyingDamage + " life from flying damage.");
				
		if (attacking.size() > blocking.size()) {
			int difference = 0;
			for (int i = blocking.size(); i<attacking.size(); i++) {
				difference += attacking.get(i).getPower();
			}
			opponentLife -= difference;
			displayAction("Opponent loses " + difference + " life from extra creatures.");
		}
		for (Card c: blockersToRemove) {
			blocking.remove(c);
			c.untap();
			putInGraveyard(c);
			displayAction("Blocker dies: " + c.getName());
		}		
		for (Card c: attackersToRemove) {
			attacking.remove(c);
			c.untap();
			displayAction("Attacker dies: " + c.getName());
			if (c.isHasBeenUnearthedAlready()) {
				displayAction(c.getName() + " has been unearthed already - removing from game");
			} else {
				putInGraveyard(c);
			}
		}		
		for (Card c : attacking) {
			board.add(c);
		}
		for (Card c : attackingWithFlying) {
			board.add(c);
		}
		for (Card c : blocking) {
			opponentBoard.add(c);
		}
		
		displayAction("Opponent now has: " + opponentBoard.size() + " creatures");						
	}

	private void playCreaturesFromHand() {
		ArrayList<Card> tempHand = new ArrayList<Card>();
		for (Card c : hand) {
			tempHand.add(c);
		}
		for (Card c : tempHand) {
			// TODO: add in preference for maximizing mana use to get most
			// possible creatures out.
			if (c.getType().equals("CREATURE")) {
				if (getAvailableMana(board) >= c.getCost()) {
					castSpell(c);
				}
			}
		}
		
	}

	private  void castSpell(Card c) {
		tapLands(c.getCost());
		hand.remove(c);
		displayAction("Casting " + c.getName());
		if (c.getType().equals("INSTANT")) {
			// for now, assume it's a bolt
			opponentLife -= c.getDamage();			
		} else {
			if (c.getType().equals(CardFactory.CREATURE) || !c.isHasHaste()) {
				c.setSummoningSick(true);
				displayAction(c.getName() + " gains summoning sickness.");
			}
			board.add(c);
		}
	}

	private  void untapAll() {
		for (Card c : board) {
			c.untap();
		}		
	}

	private  void useDDOnCreatures() {
		ArrayList<Card> tempOpponentBoard = new ArrayList<Card>();
		for (Card c : opponentBoard) {
			tempOpponentBoard.add(c);
		}
		for (Card target : tempOpponentBoard) {
			if (target.getType().equals("CREATURE")) {
				// TODO: need to refine this when there is more than one creature, based on toughness
				// TODO: right now this assumes that all DD kills a creature, this is often not the case
				
				// get lowest mana DD
				Card lowest = getLowestManaDD(hand);
				if (lowest == null) {
					return;
				}
				// check if we have mana (untapped lands in play)
				if (!(lowest.getCost() <= getAvailableMana(board))) {
					return; // not enough mana
				}
				
				if (lowest.getName().equals("Searing Blaze") && !landPlayedThisTurn) {
					continue; // TODO: improve this logic
				}
				// if we do, tap the lands and cast it
				tapLands(lowest.getCost());
				hand.remove(lowest);
				displayAction("Casting " + lowest.getName() + " on " + target.getName());
				opponentBoard.remove(target);
				putInGraveyard(lowest);				
				if (lowest.getName().equals("Searing Blaze") && landPlayedThisTurn) {
					opponentLife -= 3;
					displayAction("Opponent takes 3 damage from " + lowest.getName()); // TODO: handle this better - all edge cases
				}
			}
		}
		
	}

	private  void tapLands(int cost) {
		for (Card c : board) {
			if (c.getType().equals("LAND") && !c.isTapped()) {
				c.tap();
				cost--;
				if (cost == 0) {
					return;
				}
			}
		}
		
	}

	private  int getAvailableMana(ArrayList<Card> board2) {
		int availableMana =0;
		for (Card c : board) {
			if (c.getType().equals("LAND") && !c.isTapped()) {
				availableMana++;
			}
		}
		return availableMana;
	}

	private  Card getLowestManaDD(ArrayList<Card> hand2) {
		int lowestMana = 999999;
		Card lowest = null;
		for (Card c : hand2) {
			if (c.getType().equals(CardFactory.INSTANT) && c.getCost()<lowestMana) {
				lowest = c;
			}
		}
		return lowest;
	}

	private  void doOpponentTurn() {
		
		if(useEasyOpponent) {
			opponentBoard.add(CardFactory.makeCard(CardName.FAKE_ONE_ONE));
			displayAction("Opponent: makes a fake 1/1 creature");
			
		} else {
			// testing a more difficult opponent
			for (int i = 0; i < turn/3; i++) {
				// randomly make a 1/1 or a 2/2
				if (Math.random() > 0.5) { 
					opponentBoard.add(CardFactory.makeCard(CardName.FAKE_ONE_ONE));
					displayAction("Opponent: makes a fake 1/1 creature");
				} else {
					opponentBoard.add(CardFactory.makeCard(CardName.FAKE_TWO_TWO));
					displayAction("Opponent: makes a fake 2/2 creature");
				}
			}
		}
	}

	private  void doGameWin() {
		displayAction("A win is possible on this turn!");
		displayAction("Turn: " + turn);
		win = true;
	}

	/* TODO: This doesn't take into account the fact that we may be
	 * able to kill the opponent with multiple rounds of DD
	 * because we don't have enough mana but we DO have enough
	 * cards.
	 */
	private  boolean canKillOpponentWithDD() {
		
		// test all combinations of cards in a given hand (kicked and non-kicked counting as separate cards)
		// if any combination of cards can be cast (sum of costs <= mana available) that will kill the opponent, cast them
		//System.out.println("DEBUG: entering canKillOpponentWithDD()");
		boolean canKill = canKillOpponentWithDD(hand, getAvailableMana(board), opponentLife, new ArrayList<Card>());
		if (canKill) {
			displayAction("It is possible to kill opponent with DD.");
		}
		return canKill;
	}
	
	

	private boolean canKillOpponentWithDD(ArrayList<Card> cardsRemaining,
			int manaRemaining, int lifeRemaining, ArrayList<Card> solution) {
		
		//System.out.println("DEBUG: canKillOpponentWithDD(" + cardsRemaining.size() + ", " + manaRemaining + " , " + lifeRemaining + " , " + solution.size() + ")");
		// TODO: Kicker (treat as different cards?)

		
		
		if (cardsRemaining.size() == 0 || manaRemaining<0) {
			return false;
		}
		for (Card c : cardsRemaining) {
			boolean canKillWithKicker = false;
			if (c.isHasKicker()) {
				canKillWithKicker = c.getType().equals(CardFactory.INSTANT) && c.getDamageWithKicker()>=lifeRemaining && c.getCostWithKicker()<= manaRemaining;
			}
			if ((c.getType().equals(CardFactory.INSTANT) && c.getDamage()>=lifeRemaining && c.getCost()<= manaRemaining) || canKillWithKicker) {
				displayAction("TODO: Print all spells to cast for win 1");
				return true;
			} else {
				ArrayList<Card> tempCardsRemaining = new ArrayList<Card>();
				for (Card card : cardsRemaining) {
					tempCardsRemaining.add(card);
				}
				ArrayList<Card> tempSolution = new ArrayList<Card>();
				for (Card card : solution) {
					tempSolution.add(card);
				}
				tempCardsRemaining.remove(c);
				tempSolution.add(c); // used to display final solution
				boolean canKill = canKillOpponentWithDD(tempCardsRemaining, manaRemaining-c.getCost(), lifeRemaining-c.getDamage(), tempSolution);
				if (c.isHasKicker()) {
					boolean canKillWithKicker2 = canKillOpponentWithDD(tempCardsRemaining, manaRemaining-c.getCostWithKicker(), lifeRemaining-c.getDamageWithKicker(), tempSolution);
					canKill = (canKill || canKillWithKicker2);
				}
				if (!canKill) {
					continue;
				} else {
					displayAction("TODO: Print all spells to cast for win 2");
					return true;
				}
			}			
		}
		return false;		
	}

	private  void playNonTeeteringPeaksLand() {
		ArrayList<Card> tempHand = new ArrayList<Card>();
		for (Card c : hand) {
			tempHand.add(c);
		}
		
		// play mountains first
		for (Card c : tempHand) {			
			if (c.getName().equals("Mountain")) {
				hand.remove(c);
				board.add(c);
				displayAction("Playing card: " + c.getName());
				landPlayedThisTurn = true;
				return;
			}
		}		
		
		// Play saclands next
		for (Card c : tempHand) {			
			if (c.isSacLand()) {
				hand.remove(c);
				board.add(c);
				displayAction("Playing card: " + c.getName());
				landPlayedThisTurn = true;
				displayAction("Sacrificing " + c.getName());
				board.remove(c);
				putInGraveyard(c);
				// TODO: costs 1 life
				Card newLand = deck.getCardFromDeck("Mountain");
				if (newLand != null) {
					board.add(newLand);
				} else {
					displayAction("Tried to find a land in deck after sacrificing " + c.getName() + " but no land found!");
				}
				// TODO: Trigger landfall on any cards that use it (again)
				// TODO: This logic can be better - sometimes better to use saclands first and sometimes better to save them				
				return;
			}
		}
		
	}

	private  void displayAction(String string) {
		if (displayActions) {
			System.out.println(string);
		}
		
	}

}
